12. Exercise: Display an Internet Image

L8 19 Displaying An Internet Image HS-SC

Erratum
At timestamp 04:35 in the video above, in OverviewFragment.kt file, inside onCreateView() function, the way to set the binding lifecycle to itself has changed from binding.setLifecycleOwner(this) to binding.lifecycleOwner = this.

Now it's your turn to complete this exercise yourself! At the end of this exercise you will have downloaded and displayed your very first image from Mars.

If you want to start at this step, you can download this exercise from: Step.04-Exercise-Displaying-an-Internet-Image. You will find plenty of //TODO comments to help you complete this exercise,

  1. In build.gradle, add the Glide library dependency:
implementation "com.github.bumptech.glide:glide:$version_glide"



  1. In OverViewViewModel, rename response LiveData to status:
  private val _status = MutableLiveData<String>()

  val status: LiveData<String>
     get() = _status  
 


  1. Add an encapsulated LiveData<MarsProperty> property:
private val _property = MutableLiveData<MarsProperty>()

 val property: LiveData<MarsProperty>
     get() = _property   



  1. Update getMarsRealEstateProperties() to set _property to the first MarsProperty from listResult:
  if (listResult.size > 0) {
     _property.value = listResult[0]
  }

and the error response to a status value:

_status.value = "Failure: ${e.message}"
  1. In fragment_overview.xml change the TextView binding to viewModel.property.imgSrcUrl.
android:text="@{viewModel.property.imgSrcUrl}"


Running the app now displays the Url to the first Mars image. Next, we'll load and display that image with Glide.

  1. In BindingAdapters create a BindingAdapter to convert imgUrl to a URI with the https scheme.

    Inside the adapter, use Glide to download the image display it in imgView:

    @BindingAdapter("imageUrl")
    fun bindImage(imgView: ImageView, imgUrl: String?) {
       imgUrl?.let {
       val imgUri = imgUrl.toUri().buildUpon().scheme("https").build()
       Glide.with(imgView.context)
            .load(imgUri)
            .into(imgView)
       }
    }


  2. In grid_view_item.xml, add a viewModel data variable.

    <data>
        <variable
            name="viewModel"
            type="com.example.android.marsrealestate.overview.OverviewViewModel" />
    </data>
  1. Bind mars_image to the imageView using the recently added imgUrl BindingAdapter.
   app:imageUrl="@{viewModel.property.imgSrcUrl}"



  1. Back in OverviewFragment, replace FragmentOverviewBinding with GridViewItemBinding.
 val binding = GridViewItemBinding.inflate(inflater)



  1. Build and run your app. You should see a beautiful piece of property on Mars. Who wouldn't want to live there?

We can do one more thing to make this work even better. Currently our app doesn't display anything when we're loading, and if the loading fails there's no indication to the user.

  1. In BindingAdapters, apply RequestOptions to the Glide call to add a placeholder that displays an image while your image downloads, and an error image in case it can't be retrieved.
 .apply(RequestOptions()
         .placeholder(R.drawable.loading_animation)
         .error(R.drawable.ic_broken_image))
                    


  1. Build and run your app. You might just catch a blink of the loading animation if you have a fast connection.

If you get stuck, go back and watch the video again. Once you’re done, you can check your solution against the solution we’ve provided here: Step.04-Solution-Displaying-an-Internet-Image, or using this git diff.

Task Description:

Complete the tasks below to display an image.

Task List:

Task Feedback:

Good work! Are you ready to see some more Mars images?

Reference documentation